program main
    implicit none
    integer, parameter :: nx = 100, ny=10, nxy=1000
    include 'mpif.h'
    
    integer :: i,j,ierr, myrank, nproc   ! MPI process id and number	
	integer :: sum, rem
      integer,allocatable,dimension(:) :: sendcounts ! array describing how many elements to send to each process
      integer,allocatable,dimension(:) :: displs  ! array describing the displacements where each segment begins 
	  integer,allocatable,dimension(:,:) :: X2D
      integer,allocatable,dimension(:) :: X,Y   ! Big array on the root process 
      integer,allocatable,dimension(:) :: buffer
	  
      call MPI_INIT( ierr )
      call MPI_COMM_RANK( MPI_COMM_WORLD, myrank, ierr )
      call MPI_COMM_SIZE( MPI_COMM_WORLD, nproc, ierr )
	  
! timer
      call mpi_barrier(MPI_COMM_WORLD, ierr)	 
!	  
	  allocate(X2D(nx,ny))
      allocate(X(nxy),Y(nxy*nproc))
      allocate(buffer(0:nxy-1))	

    do i=1,nx
	   do j=1,ny
	      X2D(i,j) = i+j
		  X(j+(i-1)*ny) = X2D(i,j)  ! 2D -> 1D vector
	   enddo
	enddo  

   do i=1,nxy
     !write(*,*)i,X(i)
     buffer(i-1) = X(i)
   enddo


    allocate(sendcounts(0:nproc-1), displs(0:nproc-1))
	
    sum = 0	
    do i=0,nproc-1
        sendcounts(i) = nxy 
        displs(i) = displs(i)+ sum 
        sum=sum+sendcounts(i)
        if(myrank==0) write(*,*)sendcounts(i), displs(i) 
    enddo

! gather data from each rank to rank 0     
   call mpi_gatherv(buffer, sendcounts(myrank), MPI_INTEGER, Y, sendcounts, displs,  &
                                  MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)        
   if(ierr /=0) then
      write(*,*) 'Failed to gather data.'
   endif 
   
!#ifdef Debug   
   if(myrank==0) then
      do i=1,nxy*nproc
        write(*,*)i,Y(i)
      enddo
   endif
!#endif 
  
     call mpi_finalize(ierr)
end	  